package com.tianquan.server.handler;

import com.tianquan.common.instance.ServiceInstance;
import com.tianquan.common.message.ServiceUpdateMessage;
import com.tianquan.server.registry.ServerInstanceManager;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.Set;


/**
 * @Author: tianquan
 * @date: 2024-11-03  12:19
 * @Description: 客户端
 */
@Slf4j
@ChannelHandler.Sharable
public class ServerChannelInboundHandlerAdapterHandler extends ChannelInboundHandlerAdapter {

    private static final ChannelGroup ALL_CHANNELS = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    ServiceUpdateMessage serviceUpdateMessage;

    public static void addChannel(Channel channel) {
        ALL_CHANNELS.add(channel);
        log.info("添加后allChannels数量：{}", ALL_CHANNELS.size());
    }

    public static ChannelGroup getAllChannels() {
        log.info("allChannels数量：{}", ALL_CHANNELS.size());
        return ALL_CHANNELS;
    }

    public static void deleteChannel(Channel channel) {
        ALL_CHANNELS.remove(channel);
        log.info("删除后allChannels数量：{}", ALL_CHANNELS.size());
    }

    // 在连接建立时触发
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        new Thread(() -> {
            addChannel(ctx.channel());
        }).start();
    }

    // 在连接断开时触发
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        new Thread(() -> {
            deleteChannel(ctx.channel());
            // 关闭通道
            ctx.channel().close();
            getAllChannels().writeAndFlush(serviceUpdateMessage);
        });
    }

    // 在出现异常时触发
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        if (cause instanceof IOException || "远程主机".contains(cause.getMessage())) {
            log.info("------------客户端已断开连接---------------");
            // 获取客户端地址和端口信息
            InetSocketAddress remoteSocketAddress = (InetSocketAddress) ctx.channel().remoteAddress();
            String host = remoteSocketAddress.getHostName();
            int port = remoteSocketAddress.getPort();
            log.info("客户端IP: {},客户端端口: {}", host, port);
            // 获取当前服务实例
            ServiceInstance instance = ServerInstanceManager.getInstanceByHost(host, port);
            // 从服务器实例管理器中移除该实例
            ServerInstanceManager.removeInstanceByHost(host, port);
            // 获取删除后的所有服务实例
            Map<String, Set<ServiceInstance>> instances = ServerInstanceManager.getInstances();
            // 构建服务变更消息
            String msg = "";
            if (instance != null) {
                log.info("当前断开连接的实例对象{}", instance);
                // 构建服务变更消息
                msg = "Server Name：" + instance.getServerName() + "Address：" + instance.getHost() + ":" + instance.getPort() + "Offline";
            }
            // 主动推送服务变更消息 将新服务列表推送给所有服务
            log.info("推送服务列表：{}", instances);
            serviceUpdateMessage = new ServiceUpdateMessage(true, msg, instances);
        }
    }

}
